package com.horizon.cloud.base.filter;

import com.horizon.cloud.base.service.impl.UserLoadService;
import com.horizon.cloud.common.constants.SessionConstants;
import com.horizon.cloud.common.context.SessionHolder;
import com.horizon.cloud.common.dto.UserDTO;
import com.horizon.cloud.common.util.JsonUtil;
import com.horizon.cloud.standard.redis.RedisRepository;
import org.apache.commons.lang.StringUtils;
import org.springframework.session.Session;
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

import static com.horizon.cloud.common.context.SessionHolder.G_USER;

/**
 * CustomedSessionRepositoryFilter处理完成后，请求进入
 * 下一个过滤器SessionDataLoadFilter
 * 加载需要高速访问的数据到分布式session
 * 1.获取前面的sessionIdFilter过滤器加载的SessionId
 * 用于判断sessionID是否变化，如果变化就表明旧session不存在或者旧sessionid已经过期
 * 需要更新sessionId,并且在redis中进行缓存
 * 2.获取前面的customedSessionRepositoryFilter创建session，如果是新创建的session
 * 就加载必要的需要告诉访问的数据，比如用户基础数据，权限，校色（就是填充下这些值）
 * 以提高后续操作性能
 */
public class SessionDataLoadFilter extends OncePerRequestFilter {

    //用户权限，角色信息
    UserLoadService userLoadService;
    RedisRepository redisRepository;

    public SessionDataLoadFilter(UserLoadService userLoadService, RedisRepository redisRepository) {
        this.userLoadService = userLoadService;
        this.redisRepository = redisRepository;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        //获取前面sessionIdFilter过滤器加载的sessionId
        String sid = SessionHolder.getSid();
        HttpSession session = httpServletRequest.getSession();

        //之前的session不存在,或者和这次请求的session不同
        if (StringUtils.isEmpty(sid) ||
                !sid.equals(httpServletRequest.getSession().getId())) {
            // 取得当前的 session id
            sid = session.getId();
            // user id 和  session id  作为 key-value 保存到redis
            redisRepository.setSessionId(SessionHolder.getUserIdentifier(), sid);
            SessionHolder.setSid(sid);
        }

        /**
         *获取 session 中的用户信息
         *为空表示用户第一次发起请求，加载用户信息到 session 中
         */
        if (null == session.getAttribute(G_USER)) {
            //获取当前线程保存的userid
            String uid = SessionHolder.getUserIdentifier();
            UserDTO userDTO = null;

            //获取当前线程保存的sessionid
            if (SessionHolder.getSessionIDStore()
                    .equals(SessionConstants.SESSION_STORE)) {
                //用户端：装载用户端的用户信息
                userDTO = userLoadService
                        .loadFrontEndUser(Long.valueOf(uid));

            } else {
                //管理控制台控制台：装载管理控制台的用户信息
                userDTO = userLoadService.loadBackEndUser(Long.valueOf(uid));

            }
            /**
             * 将用户信息缓存起来
             */
            session.setAttribute(G_USER, JsonUtil.pojoToJson(userDTO));
        }

        /**
         * 将Session请求，保持到  SessionHolder 的 ThreadLocal 本地变量中，方便统一获取
         */
        SessionHolder.setSession(session);
        SessionHolder.setRequest(httpServletRequest);
        filterChain.doFilter(httpServletRequest, httpServletResponse);
    }

    /**
     * 返回true代表不执行过滤器，false代表执行
     */
    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) {
        return true;
    }
}
